package com.naiterui.ehp.bs.im.network.transcode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.naiterui.ehp.bp.constants.ImConstants;
import com.naiterui.ehp.bs.im.exception.ExceptionCodes;
import com.naiterui.ehp.bs.im.exception.NaiteruiIMException;
import com.naiterui.ehp.bs.im.network.protocl.FollowUpFillin;
import com.naiterui.ehp.bs.im.network.protocl.Media;
import com.naiterui.ehp.bs.im.network.protocl.Message;
import com.naiterui.ehp.bs.im.network.protocl.RecommandDrug;
import com.naiterui.ehp.bs.im.network.protocl.ServiceEvaluation;
import com.naiterui.ehp.bs.im.network.transcode.coders.AbstractTransCoder;
import com.naiterui.ehp.bs.im.network.transcode.coders.ConsultPaidNoticeTransCoder;
import com.naiterui.ehp.bs.im.network.transcode.coders.CustomizedMessageTransCoder;
import com.naiterui.ehp.bs.im.utils.Constants;

/**
 * 负责消息编码与解码的逻辑处理类
 */
@Service
public class MessageTransCoder implements IMessageTransCoder {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(MessageTransCoder.class);

    /**
     * 文本消息编解码器
     */
    private final AbstractTransCoder<String> textTransCoder;

    /**
     * 多媒体消息编解码器
     */
    private final AbstractTransCoder<Media> mediaTransCoder;

    /**
     * 推荐用药消息编解码器
     */
    private final AbstractTransCoder<RecommandDrug> drugRecTtransCoder;

    /**
     * 服务评价
     */
    private final AbstractTransCoder<ServiceEvaluation> serviceEvaluationTransCoder;

    /**
     * 随访表单填写通知
     */
    private final AbstractTransCoder<FollowUpFillin> followUpFillinTransCoder;

    /**
     * 患者支付付费咨询消息 解码器
     */
    private final ConsultPaidNoticeTransCoder consultPaidNoticeTransCoder;

    private final CustomizedMessageTransCoder customizedMessageTransCoder;

    public MessageTransCoder(@Qualifier(value = "textMsgTransCoder") AbstractTransCoder<String> textTransCoder, @Qualifier(value = "mediaMsgTransCoder") AbstractTransCoder<Media> mediaTransCoder, @Qualifier(value = "drugRecTransCoder") AbstractTransCoder<RecommandDrug> drugRecTtransCoder,
        @Qualifier(value = "serviceEvaluationTransCoder") AbstractTransCoder<
            ServiceEvaluation> serviceEvaluationTransCoder,
        @Qualifier(value = "followUpFillinTransCoder") AbstractTransCoder<FollowUpFillin> followUpFillinTransCoder,
        @Qualifier(value = "consultPaidNoticeTransCoder") ConsultPaidNoticeTransCoder consultPaidNoticeTransCoder,
        @Qualifier(value = "customizedMessageTransCoder") CustomizedMessageTransCoder customizedMessageTransCoder) {
        this.textTransCoder = textTransCoder;
        this.mediaTransCoder = mediaTransCoder;
        this.drugRecTtransCoder = drugRecTtransCoder;
        this.serviceEvaluationTransCoder = serviceEvaluationTransCoder;
        this.followUpFillinTransCoder = followUpFillinTransCoder;
        this.consultPaidNoticeTransCoder = consultPaidNoticeTransCoder;
        this.customizedMessageTransCoder = customizedMessageTransCoder;
    }

    /**
     * 消息编码
     */
    @Override
    public String encodeMessage(Message<?> message) throws NaiteruiIMException {

        // 编码后的消息
        String messageStr = null;

        // 根据消息类型进行编码操作
        if (message.getType() == Constants.MESSAGE_TYPE_TEXT) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_MEDIA_IMG || message.getType() == Constants.MESSAGE_TYPE_MEDIA_AUDIO
                || message.getType() == Constants.MESSAGE_TYPE_MEDIA_VIDEO) {
            messageStr = this.mediaTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_DRUG) {
            messageStr = this.drugRecTtransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PAID_CONSULT) {
            messageStr = this.consultPaidNoticeTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PATEINTS_MEDICAL_RECORD
                || message.getType() == Constants.MESSAGE_TYPE_PATIENTS_LAST_MEDICAL_RECORD
                || message.getType() == Constants.MESSAGE_TYPE_REMIND_PATIENTS_FILL_MEDICAL_RECORD) {
            messageStr = this.customizedMessageTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_DOCTORS_MEDICALRECORD) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if(message.getType() == Constants.MESSAGE_TYPE_PATIENTS_SERVICE_EVALUATION){
            messageStr = this.serviceEvaluationTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PATIENTS_DISEASE) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PATIENTS_CONSULT_FINISH) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PATIENTS_PRESCRIPTION) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PATIENTS_FIRST_BIND) {
            messageStr = this.textTransCoder.serializeMessage(message);
        }else if (message.getType() == ImConstants.MESSAGE_TYPE_FIRST_BIND_UNNAMED) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == ImConstants.MESSAGE_TYPE_INQUIRER_INFO_PERFECT) {
            messageStr = this.textTransCoder.serializeMessage(message);
        } else if (message.getType() == ImConstants.MESSAGE_TYPE_FOLLOW_UP_FILLIN) {
            messageStr = this.followUpFillinTransCoder.serializeMessage(message);
        } else {
            messageStr = this.textTransCoder.serializeMessage(message);
        }
        return messageStr;
    }

    /**
     * 消息解码
     */
    @Override
    public Message<?> decodeMessage(String message) throws NaiteruiIMException {

        // 解析消息类型
        Integer messageType;
        try {
            messageType = JSON.parseObject(message).getInteger("type");
        } catch (Exception e) {
            LOGGER.error("message is not a available json format! message is {}", message, e);
            throw new NaiteruiIMException(ExceptionCodes.MSG_FORMAT_INVALID);
        }

        // 消息构建不正确缺少必要的类型参数
        if (messageType == null) {
            LOGGER.error("not found attribute [type] in message body! message is {}", message);
            throw new NaiteruiIMException(ExceptionCodes.MSG_FORMAT_INVALID);
        }

        // 消息对象
        Message<?> messageBean;

        // 根据类型反序列化消息信息
        switch (messageType) {
            case Constants.MESSAGE_TYPE_TEXT:
            case ImConstants.MESSAGE_TYPE_FIRST_BIND_UNNAMED:
            case ImConstants.MESSAGE_TYPE_INQUIRER_INFO_PERFECT:
                messageBean = this.textTransCoder.deserializeMessage(message);
                break;
            case Constants.MESSAGE_TYPE_PATIENTS_SERVICE_EVALUATION:
                messageBean = serviceEvaluationTransCoder.deserializeMessage(message);
                break;
            case Constants.MESSAGE_TYPE_MEDIA_IMG:
            case Constants.MESSAGE_TYPE_MEDIA_AUDIO:
            case Constants.MESSAGE_TYPE_MEDIA_VIDEO:
            case ImConstants.MESSAGE_TYPE_VIDEO_IMAGE:
                messageBean = this.mediaTransCoder.deserializeMessage(message);
                break;

            case Constants.MESSAGE_TYPE_DRUG:
                messageBean = this.drugRecTtransCoder.deserializeMessage(message);
                break;
            case Constants.MESSAGE_TYPE_PAID_CONSULT:
                // 患者支付付费咨询后的通知 消息
                messageBean = this.consultPaidNoticeTransCoder.deserializeMessage(message);
                if (messageBean.getRelation().equals(Constants.MESSAGE_RESOURCE_DOCTOR)) {
                    messageBean.setVisualType(Message.MESSAGE_VISUAL_TYPE_PATIENT);
                }
                if (messageBean.getRelation().equals(Constants.MESSAGE_RESOURCE_PATIENT)) {
                    messageBean.setVisualType(Message.MESSAGE_VISUAL_TYPE_DOCTOR);
                }
                break;
            case ImConstants.MESSAGE_TYPE_FOLLOW_UP_FILLIN:
                messageBean = this.followUpFillinTransCoder.deserializeMessage(message);
                break;
            default:
                LOGGER.error("decode message found unknow message type {}, message is {}", messageType, message);
                throw new NaiteruiIMException(ExceptionCodes.MSG_FORMAT_INVALID);

        }

        // 执行消息完整性和正确性的检测
        if (!messageBean.selfValidate()) {
            throw new NaiteruiIMException(ExceptionCodes.MSG_NOT_COMPLETE);
        }

        return messageBean;
    }
}
